//! Copyright 2012 NTH Technology, Inc.
//! All rights reserved
//!
#include "stm32f10x.h"
#include "BoardHardware.h"
#include "Config.h"
#include "Capture.h"

U16 cCapture::m_Count;
U16 cCapture::m_Head;
U16 cCapture::m_Tail;
U16 cCapture::m_CaptureValue[ cConfig::MAX_CAPTURE_VALUE_STORE ];


extern "C"  {
    volatile bool s_HaveAnEventFlag;
    volatile U16  s_Capture;
    volatile U16  s_CaptureBaseTimer;
    void TIM3_IRQHandler(void)
    {
        U16 captureTimer;
        if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET) 
        {
            /* Clear TIM3 Capture compare interrupt pending bit */
            TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
            captureTimer = TIM_GetCapture2(TIM3);
            if( captureTimer >= s_CaptureBaseTimer )
            {
                s_Capture = captureTimer - s_CaptureBaseTimer;
            }
            else
            {
                s_Capture = captureTimer + (~s_CaptureBaseTimer) + 1;
            }
            s_CaptureBaseTimer = captureTimer;
            s_HaveAnEventFlag = true;

//             if(CaptureNumber == 0)
//             {
//                 /* Get the Input Capture value */
//                 IC3ReadValue1 = TIM_GetCapture2(TIM3);
//                 CaptureNumber = 1;
//             }
//             else if(CaptureNumber == 1)
//             {
//                 /* Get the Input Capture value */
//                 IC3ReadValue2 = TIM_GetCapture2(TIM3); 
// 
//                 /* Capture computation */
//                 if (IC3ReadValue2 > IC3ReadValue1)
//                 {
//                     Capture = (IC3ReadValue2 - IC3ReadValue1); 
//                 }
//                 else
//                 {
//                     Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
//                 }
//                 /* Frequency computation */ 
//                 TIM3Freq = (uint32_t) SystemCoreClock / Capture;
//                 CaptureNumber = 0;
//             }
        }
    }
};


void cCapture::InitReset()
{
    /* TIM3 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    /* GPIOA and GPIOB clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* TIM3 channel 2 pin (PA.07) configuration */
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Enable the TIM3 global Interrupt */
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM3 configuration: Input Capture mode ---------------------
        The external signal is connected to TIM3 CH2 pin (PA.07)  
        The Rising edge is used as active edge,
        The TIM3 CCR2 is used to compute the frequency value 
    ------------------------------------------------------------ */
    /* Time base configuration */
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    /* Prescaler configuration */
    /* Compute the prescaler value */
    U16 PrescalerValue = (U16) (SystemCoreClock / 1000000) - 1;
    TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);

    TIM_ICInitTypeDef  TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    /* TIM enable counter */
    TIM_Cmd(TIM3, ENABLE);

    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);

    s_HaveAnEventFlag = false;
    s_CaptureBaseTimer = 0;

    m_Count = 0;
    m_Head = 0;
    m_Tail = 0;
}


void cCapture::PushCaptureValue(U16 iValue)
{
    if ( cConfig::MAX_CAPTURE_VALUE_STORE > m_Count )
    {
        m_CaptureValue[ m_Head ] = iValue;
        if( cConfig::MAX_CAPTURE_VALUE_STORE <= ++m_Head ) m_Head = 0;
        ++m_Count;
    }
}


bool cCapture::PopCaptureValue( U16 &iValue )
{
    if( 0 < m_Count )
    {
        iValue = m_CaptureValue[ m_Tail ];
        if( cConfig::MAX_CAPTURE_VALUE_STORE <= ++m_Tail ) m_Tail = 0;
        --m_Count;
        return( true );
    }
    else
    {
        return( false );
    }
}


U16 cCapture::GetCaptureValueCount()
{
    return( m_Count );
}


void cCapture::RunOne()
{
    if( true == s_HaveAnEventFlag )
    {
        s_HaveAnEventFlag = false;
        PushCaptureValue( s_Capture );
    }
}

